package com.dc.juc.example._10_aqs;

import com.google.common.base.Throwables;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;


/**
 * Description: CyclicBarrier 循环屏障
 *  会让所有线程都等待完成后才会继续下一步行动
 *
 *  await(long timeout, TimeUnit unit)：如果在指定的时间内达到parties的数量，则程序继续向下运行，否则如果出现超时，则抛出TimeoutException异常。
 *
 *  执行的现象：因等待时间超长，因此会抛出异常，当前方法，需要与 try...catch 结合使用
 *
 * @author: gdc
 * @date: 2021/8/16
 * @version 1.0
 */
@Slf4j
public class CyclicBarrier2 {

    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(5);

    @SneakyThrows
    public static void main(String[] args){

        ExecutorService threadPool = Executors.newCachedThreadPool();

        for (int i = 0; i < 10; i++) {
            TimeUnit.SECONDS.sleep(1);
            threadPool.execute(() -> {
                race(Thread.currentThread().getId());
            });
        }

        threadPool.shutdown();

    }

    @SneakyThrows
    private static void race(long threadNum) {
        TimeUnit.SECONDS.sleep(1);
        log.info("{} is ready", threadNum);

        // 如果在指定的时间内达到parties的数量，则程序继续向下运行，否则如果出现超时，则抛出TimeoutException异常。
        // 因为存在超时异常，因此await(long timeout, TimeUnit unit)方法，需要和 try...catch块，结合使用
        try {
            cyclicBarrier.await(2000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | BrokenBarrierException | TimeoutException e) {
            log.error("错误信息：{}", Throwables.getStackTraceAsString(e));
        }
        log.info("{} continue", threadNum);
    }
}